#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/time.h>
#include "../../src/thread.h"

double getTime(){
  struct timeval tv;
  gettimeofday(&tv,NULL);
  return 1000*tv.tv_sec+tv.tv_usec/1000.0;
}

static void* threadfunc(void* arg)
{
  char *name = arg;
  printf("je suis le thread %d, lancé avec l'argument %s\n",
	 thread_self(), name);
  double t1 = getTime();
  thread_yield();
  double t2 = getTime();
printf("\nEncore le thread %d, après un thread_yield\n",
	 thread_self());
  printf("%d: cout de changement de contexte : %g\n\n", thread_self(),t2-t1);

  thread_exit(arg);
}

static void* pthreadfunc(void* arg)
{
  char *name = arg;
  printf("je suis le pthread %p, lancé avec l'argument %s\n",
	 (void*)pthread_self(), name);
  double t1 = getTime();
  sched_yield();
  double t2 = getTime();
  printf("\nEncore le pthread %p, après un sched_yield\n",
	 (void*)pthread_self());
  printf("%p: cout de changement de contexte : %g\n\n", (void*)pthread_self(),t2-t1);
  pthread_exit(arg);
}

void test_thread(){
  thread_t thread1, thread2;
  int err;

  printf("\n[TEST] : Changement de contexte - thread.h ...\n");
  err = thread_create(&thread1, threadfunc, "thread1");
  assert(!err);
  err = thread_create(&thread2, threadfunc, "thread2");
  assert(!err);
  
  err = thread_join(thread1, NULL);
  assert(!err);
  err = thread_join(thread2, NULL);
  assert(!err);
}

void test_pthread(){
  pthread_t thread1, thread2, thread3;
  int err;
  
  printf("\n[TEST] - Changement de contexte - Pthread.h ...\n");
  err = pthread_create(&thread1, NULL,pthreadfunc, "thread1");
  assert(!err);
  err = pthread_create(&thread2, NULL,pthreadfunc, "thread2");
  assert(!err);
  
  err = pthread_join(thread1, NULL);
  assert(!err);
  err = pthread_join(thread2, NULL);
  assert(!err);
}

int main(int argc, char *argv[])
{
  test_pthread();
  test_thread();
  return EXIT_SUCCESS;
}
